const socketIo = require("socket.io"); // 引入 socket.io
const chalk = require("chalk");
const getSystemMetrics = require("./systemMetrics");
const cron = require("node-cron");

/**
 * WebSocket 服务
 * @param {http.Server} server HTTP 服务器实例
 * @param {number} maxConnections 最大连接数
 * @returns {WebSocketService} WebSocket 服务实例
 */
class WebSocketService {
  constructor(server, maxConnections = 20) {
    this.io = socketIo(server); // 将 WebSocket 与 HTTP 服务绑定
    this.activeConnections = {}; // 用于追踪当前连接的用户
    // 默认有一个虚拟用户用于测试在线列表接口是否正常
    this.activeConnections["test"] = {
      handshake: {
        query: {
          userId: "test",
        },
      },
    }
    this.maxConnections = maxConnections; // 最大连接数量限制
    this.setupEvents(); // 设置事件
    this.setupMetricsCron(); // 每隔30秒获取一次系统指标 使用 node-cron 替代 setInterval
  }

  /**
   * 设置 socket 事件
   */ 
  setupEvents() {
    console.log(chalk.green("WebSocket 服务已启动"));
    this.io.on("connection", (socket) => {
      const userId = socket.handshake.query.userId; // 假设用 userId 标识每个用户
      if (!userId) {
        console.log(chalk.red("连接失败：未提供用户ID"));
        socket.emit("error", "连接失败：未提供用户ID");
        socket.disconnect(true); // 断开当前连接
        return;
      }

      // 检查是否已达最大连接数
      if (Object.keys(this.activeConnections).length >= this.maxConnections) {
        console.log(chalk.red("最大连接数已达到，拒绝连接"));
        socket.emit("error", "连接数已达到最大限制");
        // 给用户发送错误信息
        socket.disconnect(true); // 断开当前连接
        return;
      }

      // 如果该用户已连接，则断开旧连接
      if (this.activeConnections[userId]) {
        console.log(chalk.yellow(`用户 ${userId} 重复连接，断开旧连接`));
        this.activeConnections[userId].disconnect(true); // 断开之前的连接
      }

      // 保存当前连接
      this.activeConnections[userId] = socket;
      console.log(chalk.green(`用户 ${userId} 已连接`));

      // 向其他已连接的用户广播消息，告知有新用户上线
      socket.broadcast.emit("userJoined", `用户 ${userId} 已上线`);

      // 监听客户端发送的消息
      socket.on("message", (data) => {
        // 获取用户id
        const userId = socket.handshake.query.userId;
        console.log(chalk.blue("接收到客户端(" + userId + ")的消息: "), data);
      });

      // 发送欢迎消息
      socket.emit("welcome", "欢迎连接到 WebSocket 服务");

      // 监听客户端断开连接
      socket.on("disconnect", () => {
        console.log(chalk.red(`用户 ${userId} 已断开连接`));
        delete this.activeConnections[userId]; // 断开时删除用户连接
        // 广播通知其他用户，用户已离线
        socket.broadcast.emit("userLeft", `用户 ${userId} 已离线`);
      });
    });
  }
  /**
   * 获取服务器资源使用情况
   */
  setupMetricsCron() {
    // 每30秒执行一次（cron表达式：'*/30 * * * * *'）
    this.metricsCron = cron.schedule('*/30 * * * * *', async () => {
      try {
        if (Object.keys(this.activeConnections).length <= 1) { // 只有测试用户时跳过
          return;
        }
        const metrics = await getSystemMetrics();
        this.io.emit('systemMetrics', {
          timestamp: new Date().toISOString(),
          ...metrics
        });
      } catch (error) {
        console.error(chalk.red('获取系统指标失败:'), error);
      }
    }, {
      scheduled: true,
      timezone: "Asia/Shanghai" // 根据实际情况设置时区
    });
  }
}

module.exports = WebSocketService;
